#ifndef CURVESMANAGER_H
#define CURVESMANAGER_H

#include <vector>
#include <QPointF>

#include "Curves/Factories/curvefactory.h"
#include "Curves/Interfaces/icurve.h"
#include "Curves/CurveUtilities.h"
#include "curveproperties.h"

using namespace std;
using namespace Utilities;

typedef ICurve< QPointF > ICurveF;

enum JoinSmoothness
{
    C1,
    C2
};

template< class T >
void RemoveElement( vector< T >& container, int element_index )
{
    typename vector< T >::iterator it = container.begin( ) + element_index;

    copy( it + 1, container.end( ), // Source
          it );                     // Destination

    container.pop_back( );
};

class CurvesManager
{

private:
    CurveFactory< QPointF > curve_factory;
    vector< ICurveF* > curves;
    vector< CurveProperties > curve_properties;

    int active_curve_index;
    double split_point;

public:
    CurvesManager( );
    ~CurvesManager( );

    /* Curve methods. */
    void AddCurve( CurveType curve_type, int degree );
    void RemoveCurve( int curve_index );
    void MoveCurve( QPointF move_vector );
    void MoveCurves( vector< int > curves_indexes, QPointF move_vector );
    void MoveCurveUp( );
    void MoveCurveDown( );
    void Join( JoinSmoothness join_smoothness, int curve_index );
    void ElevateDegree( int degree );
    void ReduceDegree( DegreeReductionMethod method, int degree );
    void Split( );
    void RotateCurveAtCenterOfMass( double angle );
    void ActivateCurve( int curve_index );

    /* Point methods. */
    void AddPoint( QPointF point, double point_weight );
    void AddPoint( QPointF point, int point_index, double point_weight );
    void SetPointWeight( int point_index, double weight );
    void RemovePoint( );
    void RemovePoint( int point_index );
    void MovePoint( int point_index, QPointF point );
    void MovePoints( vector< int > points_indexes, QPointF vec );

    /* Curve properties methods. */
    void SetSplitPoint( double new_split_point );
    void SetCurveColor( QColor curve_color );
    void SetCurveThickness( double thickness );
    void SetControlPointsVisibility( bool state );
    void SetControlPolylineVisibility( bool state );
    void SetConvexHullVisibility( bool state );
    void SetCurveVisibility( bool state );
    void SetSelectionBoxVisibility( bool state );

    /* Getters. */
    int GetActiveCurveIndex( ) const;
    ICurve< QPointF >& GetActiveCurve( );
    ICurve< QPointF >& GetCurve( int curve_index );
    CurveProperties GetActiveCurveProperties( ) const;
    CurveProperties GetCurveProperties( int curve_index ) const;
    int GetCurveLayer( int curve_index ) const;
    double GetSplitPoint( ) const;
    int GetNumberOfCurves( ) const;

    /* Checkers;p. */
    bool CheckDrawSelectionBox( int curve_index ) const;
    bool CheckDrawControlPolyline( int curve_index ) const;
    bool CheckDrawConvexHull( int curve_index ) const;
    bool CheckDrawCurve( int curve_index ) const;
    bool CheckDrawControlPoints( int curve_index ) const;

private:

};

#endif // CURVESMANAGER_H
